import React, {PureComponent, Fragment} from 'react';
import {connect} from 'dva';
import moment from 'moment';

import {
  Form,
  Card,
  Button,
  Modal,
  Input,
  Cascader,
  Table,
  Divider,
  Popconfirm,
  Tree,
  Col,
  Row,
} from 'antd';

import PageHeaderLayout from '../../layouts/PageHeaderLayout';

import styles from './Role.less';
import StandardTable from '../../components/StandardTable';

const FormItem = Form.Item;
const {TreeNode} = Tree;

const editDeptSelector = values => {
  return values.map(dept => {
    if (dept.children && dept.children.length > 0) {
      return {
        value: dept.id,
        label: dept.name,
        parentValue: dept.parentId,
        children: editDeptSelector(dept.children),
      };
    } else {
      return {
        value: dept.id,
        label: dept.name,
        parentValue: dept.parentId,
      };
    }
  });
};

@connect(({roles, loading}) => ({
  roles,
  loading: loading.models.roles,
}))
@Form.create()
export default class Role extends PureComponent {
  state = {
    modalVisible: false,
    selectedRows:[],
    modalWidth: (window.innerWidth / 3),
    modalAction: 'add',
    formValues: {},
    deptTree: [],
    authModalVisible: false,
    selectedRoleId: null,
    checkedMenus: [],
  };

  componentDidMount() {
    window.addEventListener('resize', this.resize);
    const {dispatch} = this.props;
    dispatch({
      type: 'roles/fetch',
    });
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.resize);
  }

  onDeptChange = val => {
    const {formValues} = this.state;
    this.setState({
      formValues: {
        ...formValues,
        roleDeptId: val[val.length - 1],
      },
    });
  };

  onHandleOk = (handleOk) => {
    const {form} = this.props;
    form.validateFields((err, fieldsValue) => {
      if (err) return;
      form.resetFields();
      handleOk(fieldsValue);
    });
  };

  onRoleTreeCheck = (checkedKeys) => {
    this.setState({
      checkedMenus: checkedKeys.checked,
    })
  };

  handleAddModalVisible = flag => {
    const t = this;
    if (flag) {
      const {dispatch} = t.props;
      dispatch({
        type: 'roles/fetchDeptList',
      }).then(() => {
        const {
          roles: {deptList},
        } = t.props;
        t.setState({
          modalVisible: true,
          modalAction: 'add',
          formValues: {},
          deptTree: editDeptSelector(deptList),
        });
      });
    } else {
      t.setState({
        modalVisible: false,
      });
    }
  };

  resize = () => {
    this.setState({
      modalWidth: (window.innerWidth / 3),
    });
  };

  handleUpdModalVisible = (flag, role) => {
    const t = this;
    if (flag) {
      const {dispatch} = t.props;
      dispatch({
        type: 'roles/initDept',
        payload: {
          deptId: role.roleDeptId,
        },
      }).then(() => {
        const {
          form,
          roles: {deptList, deptIds},
        } = t.props;
        form.setFieldsValue({
          roleName: role.roleName,
          roleCode: role.roleCode,
          roleDesc: role.roleDesc,
          deptValue: deptIds.reverse(),
        });
        t.setState({
          modalVisible: true,
          modalAction: 'update',
          formValues: {
            roleId: role.roleId,
            deptName: role.deptName,
            roleDeptId: role.roleDeptId,
            createTime: role.createTime,
            updateTime: role.updateTime,
          },
          deptTree: editDeptSelector(deptList),
        });
      });
    } else {
      const {form} = this.props;
      form.resetFields();
      t.setState({
        modalVisible: false,
      });
    }
  };

  handleAuthModalVisible = (flag, role) => {
    const t = this;
    if (flag) {
      const {dispatch} = t.props;
      dispatch({
        type: 'roles/initMenuTree',
        payload: {
          roleCode: role.roleCode,
        },
      }).then(() => {
        const {
          roles: {roleMenuTree},
        } = t.props;
        t.setState({
          authModalVisible: true,
          checkedMenus: roleMenuTree.map(item => item.menuId.toString()),
          selectedRoleId: role.roleId,
        });
      });
    } else {
      t.setState({
        authModalVisible: false,
        checkedMenus: [],
        selectedRoleId: null,
      });
    }
  };

  handleAdd = fieldsValue => {
    const {dispatch} = this.props;
    const {formValues} = this.state;
    const params = {
      roleCode: fieldsValue.roleCode,
      roleName: fieldsValue.roleName,
      roleDesc: fieldsValue.roleDesc,
      roleDeptId: formValues.roleDeptId,
    };
    dispatch({
      type: 'roles/add',
      payload: {
        ...params,
      },
    });

    this.setState({
      modalVisible: false,
    });
  };

  handleUpd = fieldsValue => {
    const {dispatch} = this.props;
    const {formValues} = this.state;
    const params = {
      roleId: formValues.roleId,
      roleCode: fieldsValue.roleCode,
      roleName: fieldsValue.roleName,
      roleDesc: fieldsValue.roleDesc,
      roleDeptId: formValues.roleDeptId,
    };
    dispatch({
      type: 'roles/upd',
      payload: {
        ...params,
      },
    });

    this.setState({
      modalVisible: false,
    });
  };

  handleDel = role => {
    const {dispatch} = this.props;
    dispatch({
      type: 'roles/del',
      payload: {
        roleId: role.roleId,
      },
    });

    this.setState({
      modalVisible: false,
    });
  };

  handleUpdRoleMenu = () => {

    const {checkedMenus, selectedRoleId} = this.state;
    const {dispatch} = this.props;
    dispatch({
      type: 'roles/updRoleMenu',
      payload: {
        roleId: selectedRoleId,
        menuIds: checkedMenus.map(id => Number(id)),
      },
    }).then(
      this.setState({
        authModalVisible: false,
        checkedMenus: [],
        selectedRoleId: null,
      })
    );

  };

  handleTableChange = (pagination, filtersArg, sorter) => {
    const {dispatch} = this.props;
    const {formValues} = this.state;

    const filters = Object.keys(filtersArg).reduce((obj, key) => {
      const newObj = {...obj};
      newObj[key] = getValue(filtersArg[key]);
      return newObj;
    }, {});

    const params = {
      page: pagination.current,
      limit: pagination.pageSize,
      ...formValues,
      ...filters,
    };

    if (sorter.field) {
      params.orderByField = `${sorter.field}`;
      if (sorter.order === 'ascend') {
        params.isAsc = true
      } else if (sorter.order === 'descend') {
        params.isAsc = false
      }
    }

    dispatch({
      type: 'roles/fetch',
      payload: params,
    });
  };

  renderTreeNodes = (data) => {
    return data.map((item) => {
      if (item.children) {
        return (
          <TreeNode title={item.name} key={item.id} dataRef={item}>
            {this.renderTreeNodes(item.children)}
          </TreeNode>
        );
      }
      return <TreeNode title={item.name} key={item.id} />;
    });
  };

  render() {
    const {
      modalVisible,
      modalWidth,
      modalAction,
      authModalVisible,
      formValues,
      deptTree,
      selectedRows,
      checkedMenus,
    } = this.state;
    const {
      form,
      roles: {roles, allMenuTree},
      loading,
    } = this.props;

    const columns = [
      {
        title: '序号',
        dataIndex: 'roleId',
      },
      {
        title: '角色名称',
        dataIndex: 'roleName',
      },
      {
        title: '角色标识',
        dataIndex: 'roleCode',
      },
      {
        title: '角色描述',
        dataIndex: 'roleDesc',
      },
      {
        title: '所属部门',
        dataIndex: 'deptName',
      },
      {
        title: '创建时间',
        dataIndex: 'createTime',
        render: createTime => moment(createTime).format('YYYY-MM-DD HH:mm'),
      },
      {
        title: '操作',
        render: (_, role) => (
          <Fragment>
            <a onClick={() => this.handleUpdModalVisible(true, role)}>编辑</a>
            <Divider type="vertical" />
            <Popconfirm title="确定删除?" onConfirm={() => this.handleDel(role)} okText="删除" cancelText="取消">
              <a>删除</a>
            </Popconfirm>
            <Divider type="vertical" />
            <a onClick={() => this.handleAuthModalVisible(true, role)}>权限</a>
          </Fragment>
        ),
      },
    ];

    const modalFormItemLayout = {
      labelCol: {span: 24},
      wrapperCol: {span: 24},
    };

    let modalProps = {};
    if (modalAction === 'add') {
      modalProps = {
        handleOk: this.handleAdd,
        handleModalVisible: this.handleAddModalVisible,
        onDeptChange: this.onDeptChange,
        modalTitle: '新建角色',
        deptTree,
      };
    } else if (modalAction === 'update') {
      modalProps = {
        handleOk: this.handleUpd,
        handleModalVisible: this.handleUpdModalVisible,
        onDeptChange: this.onDeptChange,
        modalTitle: '修改角色',
        formValues,
        deptTree,
      };
    }

    return (
      <PageHeaderLayout title="角色管理">
        <Card bordered={false}>
          <div className={styles.tableList}>
            <div className={styles.tableListOperator}>
              <Button icon="plus" type="primary" onClick={() => this.handleAddModalVisible(true)}>
                新建
              </Button>
            </div>
            <StandardTable
              selectedRows={selectedRows}
              loading={loading}
              data={roles}
              rowKey="roleId"
              columns={columns}
              onChange={this.handleTableChange}
            />
          </div>
        </Card>
        <Modal
          title={modalProps.modalTitle}
          width={modalWidth}
          visible={modalVisible}
          onOk={() => this.onHandleOk(modalProps.handleOk)}
          onCancel={() => modalProps.handleModalVisible()}
        >
          <Form layout="vertical">
            <Row>
              <Col>
                <FormItem {...modalFormItemLayout} label="角色名称">
                  {form.getFieldDecorator('roleName', {
                    rules: [{min: 2, max: 20, required: true, message: '长度在2到20个字符'}],
                  })(<Input placeholder="请输入" />)}
                </FormItem>
              </Col>
            </Row>
            <Row>
              <Col>
                <FormItem {...modalFormItemLayout} label="角色标识">
                  {form.getFieldDecorator('roleCode', {
                    rules: [{min: 2, max: 20, required: true, message: '长度在2到20个字符'}],
                  })(<Input placeholder="请输入" />)}
                </FormItem>
              </Col>
            </Row>
            <Row>
              <Col>
                <FormItem {...modalFormItemLayout} label="角色描述">
                  {form.getFieldDecorator('roleDesc', {
                    rules: [{min: 2, max: 20, required: true, message: '长度在2到20个字符'}],
                  })(<Input placeholder="请输入" />)}
                </FormItem>
              </Col>
            </Row>
            <Row>
              <Col>
                <FormItem {...modalFormItemLayout} label="所属部门">
                  {form.getFieldDecorator('deptValue', {
                    rules: [{required: true, message: '必填'}],
                  })(
                    <Cascader
                      options={deptTree}
                      onChange={modalProps.onDeptChange}
                      changeOnSelect
                    />
                  )}
                </FormItem>
              </Col>
            </Row>
          </Form>
        </Modal>
        <Modal
          title="权限设置"
          width={modalWidth}
          visible={authModalVisible}
          bodyStyle={{maxHeight: 540, overflowY: 'auto'}}
          onOk={() => this.handleUpdRoleMenu()}
          onCancel={() => this.handleAuthModalVisible(false)}
        >
          <Tree
            checkable
            checkStrictly
            showLine
            defaultExpandAll
            onCheck={this.onRoleTreeCheck}
            checkedKeys={checkedMenus}
          >
            {this.renderTreeNodes(allMenuTree)}
          </Tree>
        </Modal>
      </PageHeaderLayout>
    );
  }
}
